﻿using System;
using System.Collections;
using System.Globalization;
using System.IO;
using System.Net;
using System.Text;

namespace Songhay.Net
{
    using Songhay.Xml;

    /// <summary>
    /// Static members for <see cref="System.Net.WebRequest"/>.
    /// </summary>
    public static class HttpVerbUtility
    {
        #region HTTP GET overloads:

        /// <summary>
        /// Returns the result of an HTTP GET.
        /// </summary>
        /// <param name="resourceIndicator">The location of GET</param>
        public static string Get(Uri resourceIndicator)
        {
            return Get(resourceIndicator, null, true);
        }

        /// <summary>
        /// Returns the result of an HTTP GET.
        /// </summary>
        /// <param name="resourceIndicator">The location of GET</param>
        /// <param name="proxyLocation">The proxy server location</param>
        /// <param name="bypassProxy">When <c>true</c> do not use the specified proxy server</param>
        public static string Get(Uri resourceIndicator, Uri proxyLocation, bool bypassProxy)
        {
            string ret = string.Empty;

            WebRequest request = WebRequest.Create(resourceIndicator);

            request.Credentials = CredentialCache.DefaultNetworkCredentials;

            if((proxyLocation != null) && (!string.IsNullOrEmpty(proxyLocation.AbsoluteUri)))
                request.Proxy = new System.Net.WebProxy(proxyLocation, bypassProxy);

            WebResponse response = request.GetResponse();
            using(StreamReader sr = new StreamReader(response.GetResponseStream()))
            {
                ret = sr.ReadToEnd().Trim();
            }

            return ret;
        }

        #endregion

        #region POST overloads:

        /// <summary>
        /// Returns the result of an HTTP POST.
        /// </summary>
        /// <param name="resourceIndicator">The POST location</param>
        /// <param name="postData">The data for POST</param>
        public static string Post(Uri resourceIndicator, Hashtable postData)
        {
            return Post(resourceIndicator, postData, null, true);
        }


        /// <summary>
        /// Returns the result of an HTTP POST.
        /// </summary>
        /// <param name="resourceIndicator">The POST location</param>
        /// <param name="postData">The data for POST</param>
        /// <param name="proxyLocation">The proxy server location</param>
        /// <param name="bypassProxy">When <c>true</c> do not use the specified proxy server</param>
        public static string Post(Uri resourceIndicator, Hashtable postData, Uri proxyLocation, bool bypassProxy)
        {
            string ret = string.Empty;

            WebRequest request = WebRequest.Create(resourceIndicator);
            request.Credentials = CredentialCache.DefaultNetworkCredentials;

            if((proxyLocation != null) && (!string.IsNullOrEmpty(proxyLocation.AbsoluteUri)))
                request.Proxy = new System.Net.WebProxy(proxyLocation, bypassProxy);

            request.ContentType = "application/x-www-form-urlencoded";
            request.Method = "POST";

            string postParams = GetPostData(postData);
            byte[] bytes = Encoding.UTF8.GetBytes(postParams);
            request.ContentLength = bytes.Length;

            using(Stream s = request.GetRequestStream())
            {
                s.Write(bytes, 0, bytes.Length);
            }

            WebResponse response = request.GetResponse();
            if(response != null)
            {
                using(StreamReader sr = new StreamReader(response.GetResponseStream()))
                {
                    ret = sr.ReadToEnd().Trim();
                }
            }

            return ret;
        }

        #endregion

        #region XML POST overloads:

        /// <summary>
        /// Returns the result of a POST with XML over HTTP.
        /// </summary>
        /// <param name="resourceIndicator">The POST location</param>
        /// <param name="xmlFragment">The XML data for POST</param>
        public static string XmlPost(Uri resourceIndicator, string xmlFragment)
        {
            return XmlPost(resourceIndicator, xmlFragment, null, true);
        }


        /// <summary>
        /// Returns the result of a POST with XML over HTTP.
        /// </summary>
        /// <param name="resourceIndicator">The POST location</param>
        /// <param name="xmlFragment">The XML data for POST</param>
        /// <param name="proxyLocation">The proxy server location</param>
        /// <param name="bypassProxy">When <c>true</c> do not use the specified proxy server</param>
        public static string XmlPost(Uri resourceIndicator, string xmlFragment, Uri proxyLocation, bool bypassProxy)
        {
            string ret = string.Empty;

            HttpWebRequest request = WebRequest.Create(resourceIndicator) as HttpWebRequest;

            request.Credentials = CredentialCache.DefaultNetworkCredentials;

            if((proxyLocation != null) && (!string.IsNullOrEmpty(proxyLocation.AbsoluteUri)))
                request.Proxy = new System.Net.WebProxy(proxyLocation, bypassProxy);

            request.ContentType = "text/xml";
            request.Method = "POST";

            byte[] bytes = Encoding.UTF8.GetBytes(xmlFragment);
            request.ContentLength = bytes.Length;

            using(Stream s = request.GetRequestStream())
            {
                s.Write(bytes, 0, bytes.Length);
            }

            using(HttpWebResponse response = (HttpWebResponse)request.GetResponse())
            {
                if((response != null) && (response.StatusCode != HttpStatusCode.OK))
                {
                    ret = XmlUtility.GetInternalMessage("XML Post Failed",
                        response.StatusCode.ToString(), new string[] { response.StatusDescription });
                }
                else
                {
                    using(StreamReader sr = new StreamReader(response.GetResponseStream()))
                    {
                        ret = sr.ReadToEnd().Trim();
                    }
                }
            }

            return ret;
        }

        #endregion

        private static string GetPostData(Hashtable postData)
        {
            StringBuilder sb = new StringBuilder();
            string s = sb.ToString();

            foreach(DictionaryEntry entry in postData)
            {
                s = (string.IsNullOrEmpty(s))
                    ? string.Format(CultureInfo.InvariantCulture, "{0}={1}", entry.Key, entry.Value)
                    : string.Format(CultureInfo.InvariantCulture, "&{0}={1}", entry.Key, entry.Value);
                sb.Append(s);
            }

            return sb.ToString();
        }
    }
}
